class utf8(str):
    ''' This is a subclass of str. it can take unicode or byte str 
    in utf-8 format as parameter, and analyse passed data in compliance
    with utf-8 notation, meaning the characters which were consisted 
    of more than one byte will be picked up, it handle them as integral 
    characters (not byte set anymore). Consequently its method such as 
    len, slice, getitem,etc. will behave just like a native utf-8 string do.
    it can process text data in multibyte utf-8 encodinge conveniently,
    especially useful for east asian languages.
    '''
    __idx_typ_err = TypeError('utf8 indices must be integers')
    __idx_err = IndexError('utf8 index out of range')
    def __new__(cls, data):
        if isinstance(data,unicode):
            data = data.encode('utf-8')
        inst = super(utf8,cls).__new__(cls,data)
        #make a utf-8 to byte string index
        inst.__idx, inst.__len = utf8._analyse(str(inst))
        inst.__start = 0 #iteration start point
        return inst
    
    def __getitem__(self,i):
        try:
            if i > self.__len :
                raise IndexError
            idx = self.__idx[i]
        except IndexError:
            raise self.__idx_err
        except:
            raise __idx_typ_err
        return str.__getslice__(self,idx,self.__idx[i+1])
    def __getslice__( self, i, j):
        i, j = self.__getrim(i), self.__getrim(j)
        return str.__getslice__(self,i,j)
    def __getrim(self,i):
        try:
            r = self.__idx[i]
        except IndexError:
            r = (self.__idx[-1]-1 if r < 0 else self.__idx[-1])
        except :
            raise
        return r   
    @staticmethod
    def _analyse(s):
        idx,i  = [0],0
        #check BOM if found start the idx after it
        BOM = chr(0xef) + chr(0xbb) + chr(0xbf)
        s_len = len(s)
        if s_len >= 3 and s[0:3]==BOM:
            i = 3
        idx[0] = i  #this idx has one more item than real utf8 str length,therefore
                    #length of char_n can be calculated by idx[n+1]-idx[n]
        #If the str is empty, return here
        if s_len <= i:
            return idx
        #check the primitive str byte for byte, if multibyte char is
        #found, its length will be determined. the Idx for every char will
        #be set according to individual char length
        type_err = lambda byte,i: TypeError("utf8 codec can't decode byte %s in position %d" %(byte,i))
        while i < s_len:
            try:
                byte = ord(s[i])
                if byte >> 7 == 0:
                    step = 1
                elif byte >> 5 == 6 and ord(s[i+1]) >> 6 == 2:
                    step = 2
                elif byte >> 4 == 14 and (ord(s[i+1]) >> 6 == 2
                        and ord(s[i+2]) >> 6 == 2):
                    step = 3
                elif byte >> 3 == 30 and (ord(s[i+1]) >> 6 == 2 and
                        ord(s[i+2]) >> 6 == 2 and
                        ord(s[i+3]) >> 6 == 2):
                    step = 4
                else:
                    raise type_err(byte,i)
                i +=step
                idx.append(i)
            except IndexError:
                raise type_err(byte,i)
        return idx,i-1
    def __len__(self):
        return self.__len
    def __iter__(self):
        self.__start = 0
        return self
    def next(self):
        if self.__start < self.__len:
            r = self.__getitem__(self.__start)
            self.__start +=1
            return r
        else:
            raise StopIteration